// =================================================================================================
//
//	CopyEngine Framework
//	Copyright 2012 Eran. All Rights Reserved.
//
//	This program is free software. You can redistribute and/or modify it
//	in accordance with the terms of the accompanying license agreement.
//
// =================================================================================================

package copyengine.utils.packerbox.box
{
	import flash.geom.Point;
	import flash.geom.Rectangle;

	import copyengine.utils.packerbox.data.CEPackerElementData;

	/**
	 *使用像素级的检测来确定新的Element是否Fit当前Box
	 */
	public final class CEPackerBoxPixel implements ICEPackerBox
	{
		//箱子一定是方形的
		private var mboxSize:int;

		//当前箱子里面装的所有PackerElementData
		private var mAllBoxElement:Vector.<CEPackerElementData>;

		//已经在Box里面的组件,
		private var mInBoxElementRe:Rectangle;

		private var mBoxName:String;



		//当前检测的Pixel点
		private var mTestPixelPoint:Point;
		//检测Element的矩形
		private var mTestRe:Rectangle;
		//最大的检测点
		private var mMaxTestPoint:Point;

		public function CEPackerBoxPixel()
		{
		}

		//============================================//
		//==Initialize&Dispose  Function
		//============================================//

		public function initialize(_boxSize:int, _boxName:String):void
		{
			mboxSize=_boxSize;
			mBoxName=_boxName;
			mAllBoxElement=new Vector.<CEPackerElementData>();
			mTestPixelPoint=new Point();
			mTestRe=new Rectangle();
			mMaxTestPoint=new Point();
			mInBoxElementRe=new Rectangle();
		}

		//============================================//
		//==Public Interface  Function
		//============================================//

		public function getBoxSize():int  { return mboxSize; }

		public function getBoxName():String  { return mBoxName; }

		public function getAllBoxElement():Vector.<CEPackerElementData>  { return mAllBoxElement; }

		/**
		 * 尝试缩小当前Box的尺寸
		 * 如果创建的Box尺寸是DEFAULT_BOX_SIZE,则有可能会出现Box没有用满的情况,此时
		 * 一级一级的减小尺寸,直到不能装下为止
		 */
		public function tryToNarrowDownBox():void
		{
			if (mboxSize <= CEPackerBoxConfig.DEFAULT_BOX_SIZE)
			{
				var isCanFit:Boolean=true;
				while (isCanFit)
				{
					var currentBoxSize:int=mboxSize;
					//原始的Box中的元素
					var originalAllBoxElementVector:Vector.<CEPackerElementData>=new Vector.<CEPackerElementData>();
					//原始的Box大小
					var originalBoxSize:int=currentBoxSize;
					//Loop循环使用的Element,因为每次tryToAddToBox 都会改变Re的尺寸
					//这样如果没有Fit情况 这些数据就已经是脏数据了 需要直接扔掉,换回原来的,所以需要保证
					//originalAllBoxElementVector中的数据一直是干净的 没有变过的
					var loopAllBoxElementVector:Vector.<CEPackerElementData>=new Vector.<CEPackerElementData>();

					for (var i:int=0; i < mAllBoxElement.length; i++)
					{
						originalAllBoxElementVector.push(mAllBoxElement[i].clone());
						loopAllBoxElementVector.push(mAllBoxElement[i].clone());
					}

					mAllBoxElement.length=0;
					mboxSize=currentBoxSize >> 1;

					if (currentBoxSize <= 0)
					{
						isCanFit=false;
					}
					else
					{
						for (var j:int=0; j < originalAllBoxElementVector.length; j++)
						{
							if (!tryToAddToBox(loopAllBoxElementVector[j]))
							{
								isCanFit=false;
								//无法再次缩小,回复到上次逻辑后返回
								break;
							}
						}
					}

					if (!isCanFit)
					{
						//本次循环尝试失败,修正到上一次的数据然后返回
						mAllBoxElement=originalAllBoxElementVector;
						mboxSize=originalBoxSize;
					}
				}
			}
		}

		public function tryToAddToBox(_element:CEPackerElementData):Boolean
		{
			mMaxTestPoint.x=mboxSize - _element.bitmapData.width;
			mMaxTestPoint.y=mboxSize - _element.bitmapData.height;
			mTestPixelPoint.x=mTestPixelPoint.y=0;
			mTestRe.width=_element.bitmapData.width;
			mTestRe.height=_element.bitmapData.height;
			var isCanFit:Boolean=false;

			//逐行扫描,每次都轮询所有的像素值,如果不发生碰撞就认为可以放进去
			while (mTestPixelPoint.y <= mMaxTestPoint.y)
			{
				//====横向扫描
				while (mTestPixelPoint.x <= mMaxTestPoint.x)
				{
					mTestRe.x=mTestPixelPoint.x;
					mTestRe.y=mTestPixelPoint.y;
					var length:int=mAllBoxElement.length;

					//===查询所有已经Push进去的元素,如果碰撞则更改mTestPixelPoint
					isCanFit=true;
					for (var i:int=0; i < length; i++)
					{
						var inBoxElement:CEPackerElementData=mAllBoxElement[i];
						mInBoxElementRe.copyFrom(inBoxElement.bitmapDataRe);

						mInBoxElementRe.width+=CEPackerBoxConfig.PADDING;
						mInBoxElementRe.height+=CEPackerBoxConfig.PADDING
						if (mInBoxElementRe.intersects(mTestRe))
						{
							mTestPixelPoint.x=mInBoxElementRe.right;
							isCanFit=false;
							break;
						}
					}

					//====当前所有元素都和现有元素不发生碰撞,可以Fit,否则增加x值继续查询
					if (isCanFit)
					{
						break;
					}
					else
					{
						mTestPixelPoint.x++;
					}
				}
				//===横排扫描结束
				if (isCanFit)
				{
					break;
				}
				else
				{
					mTestPixelPoint.x=0;
					mTestPixelPoint.y++;
				}
			}

			if (isCanFit)
			{
				_element.bitmapDataRe=new Rectangle(mTestPixelPoint.x, mTestPixelPoint.y, _element.bitmapData.width, _element.bitmapData.height);
				mAllBoxElement.push(_element);
				return true
			}
			else
			{
				return false;
			}

		}
	}
}
